import time
import json
import os 
import tf_dry
import rs485_rtu
import net_4G
import rtc_dry
import led_controller
import sensors_interface
import seial_port232
import ai_dry
import app_config



sensor_instan = None
collect_flag = 0
max_wait_time = 1    # 单位分钟


# 读取传感器数据回调
def collected_data_handler(sensor_name=None,**kwargs):
    global sensor_instan
    if not sensor_instan:
        print('sensor is not init')
        return []
    return sensor_instan.read_sensor(sensor_name, **kwargs)

# 从屏幕或者软件读取RTC时间 
def rtc_handler(new_time=None):
    # 如果传入了参数，则设置时间（系统时间），并同步写入RTC-UTC
    if new_time is not None:
        s = str(new_time).strip()
        local_time_str = None
        # 支持 14 位上位机格式：YYMMWWDDHHMMSS（忽略周信息）
        if len(s) == 14 and s.isdigit():
            year = f"20{s[0:2]}"
            month = s[2:4]
            # week = s[4:6]  # 周信息忽略
            day = s[6:8]
            hour = s[8:10]
            minute = s[10:12]
            second = s[12:14]
            local_time_str = f"{year}-{month}-{day} {hour}:{minute}:{second}"
        # 支持标准格式："YYYY-MM-DD HH:MM:SS"
        elif len(s) == 19 and s[4] == '-' and s[7] == '-' and s[10] == ' ' and s[13] == ':' and s[16] == ':':
            local_time_str = s
        else:
            print(f"Invalid time format for rtc_handler: {s}")
        if local_time_str:
            if rtc_dry.set_rtc(local_time_str):
                print('rtc set success')
            else:
                print('rtc set failed')
    d = rtc_dry.get_sys_time()
    # print("current RTC time:",d)
    return d


def main():
# led 初始化
    led_drv = led_controller.LEDController()
# 启动时从RTC恢复系统时间（RTC为UTC）
    rtc_dry.rtc_write_sys()
# 4G网络连接
    # net_4G.connect_4g_forever()
    # rtc_dry.sync_time_with_ntp()
    # time.sleep(1)
    # 初始化
# 变量
    global sensor_instan,max_wait_time
    global collect_flag
# # 创建传感器实例

# 创建tf卡接口实例
    tf = tf_dry.SetTfCard()
    csv_header = app_config.read_headers_from_config()
# 创建rs232实例
    uart_proj = seial_port232.HmiDrver()
# 注册串口屏接收数据回调
    uart_proj.register_calback(collected_data_handler)
# 注册触摸屏RTC接口回调
    uart_proj.register_rtc_calback(rtc_handler)
# 注册tf卡接口回调
    uart_proj.register_tf_calback(tf)   
# 注册表头更新回调（由上位机触发）
# 创建传感器接口实例
    sensor_instan = sensors_interface.SensorInterface()
 # 注册传感器参数数据
    #方式1：注册单个传感器
    # sensor_instan.register_sensor(soil =(soil_sensor,'read_soil_sensor')) 
    # 方式2：注册多实例传感器（适合大量相同类型但参数不同的传感器）
    sensor_instan.register_sensor(
                soil={
                        "sensor": rs485_rtu,             
                        "method": "read_virtual_soil_sensor",     # 虚拟函数read_virtual_soil_sensor/实际函数read_soil_sensor
                        "instances": [
                                        {"name": "No1", "params": {"addr": 1}},
                                        {"name": "No2", "params": {"addr": 2}},
                                        {"name": "No3", "params": {"addr": 3}},
                                        {"name": "No4", "params": {"addr": 4}},
                                        {"name": "No5", "params": {"addr": 5}},
                                        {"name": "No6", "params": {"addr": 6}}
                                    ]
                    }
                )
 
    last_collection_time = None
    last_next_time = None    
    led_drv.led_blink('sta',1,10)

# 进入低功耗

# 主循环
    while True:
        # 读取方式1：读取所有传感器
        # data  = collected_data_handler()
        # 读取方式2：读取特定传感器
        # soil1_data = collected_data_handler('soil1')
        # 读取方式3：临时指定参数（覆盖注册时的参数）
        # 获取当前时间
        # 获取当前时间
        if uart_proj.get_collect_flag():
            # 获取系统时间
            current_time_tuple = rtc_dry.get_sys_time()
            # 只在需要时计算下次采集时间
            if last_collection_time is None or current_time_tuple != last_collection_time:
                interval = uart_proj.get_interval()
                # 使用新的函数，直接传入时间字符串
                next_time, wait_seconds = rtc_dry.get_next_collection_time_with_time(int(interval))
                # next_time, wait_seconds = rtc_instan.get_next_collection_time_with_time(300)
                print("Wait seconds:", wait_seconds)
                # print("Next time: ", next_time)  # 调试信息
                # 判断是否到了采集时间（容忍2秒误差）
                if wait_seconds <= 7 and next_time != last_next_time:
                    # 低功耗模式  
                    led_drv.led_on('sta',5)
                    if wait_seconds > 2:
                        time.sleep(wait_seconds - 2)  # 等待到采集时间前2秒
                    # print("-------开始采集数据-------")
                    data = collected_data_handler()  
                    data_list = []
                    # print("TF data:",data)
                    power_votage = ai_dry.get_vbat_val()   # 读取供电电压

                    data_list.append(data['No1'][0]/10)
                    data_list.append(data['No1'][1]/10) 
                    data_list.append(data['No2'][0]/10)
                    data_list.append(data['No2'][1]/10)
                    data_list.append(data['No3'][0]/10)
                    data_list.append(data['No3'][1]/10) 
                    data_list.append(data['No4'][0]/10)
                    data_list.append(data['No4'][1]/10)
                    data_list.append(data['No5'][0]/10)
                    data_list.append(data['No5'][1]/10) 
                    data_list.append(data['No6'][0]/10)
                    data_list.append(data['No6'][1]/10)
                    data_list.append(power_votage)
                    print(data_list)
                # 存储数据到TF卡
                    tf.wirte_to_csv(csv_header,data_list) 
                     
                #  记录采集时间，避免重复采集
                    last_collection_time = current_time_tuple
                    last_next_time = next_time
                    # 采集完成后等待
                    # time.sleep(0.5) 
                    # 低功耗模式
                  
                else:
                    #动态等待时间
                    if wait_seconds > 7:
                        # 如果等待时间较长，分段睡眠
                        time.sleep(min(wait_seconds - 5, 60))  # 留60秒缓冲
                    else:
                        # 等待时间较短，精确睡眠
                        time.sleep(max(wait_seconds - 1, 0.5))  # 留1秒缓冲 
            else:
                # 短暂等待
                time.sleep(1)
        else:
            time.sleep(1)
            collect_flag += 1
            if collect_flag >= max_wait_time *60:
                collect_flag = 0
                uart_proj.set_collect_flag(True)
                collect_flag = 0
        




if __name__ == "__main__":  
    main()
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
       
    
    